interface UserX {
  name: string
  age: number
}

type Result = Promise<UserX>
// infer就是推导泛型参数
// infer声明只能出现在extends子语句中
type PromiseRes<T> = T extends Promise<infer R> ? R : never
/*  1 如果传入的泛型参数 `T` 是一个 Promise 类型 
（并且这个 Promise 解析后的类型是 `R`），
 那么 `PromiseRes<T>` 的类型就是 `R`。  
 2 如果 `T` 不是 Promise 类型，
 那么 `PromiseRes<T>` 的类型就是 `never`。
 这里使用了 `infer` 关键字来推断 Promise 解析后的类型。 */
type r = PromiseRes<Result>
/* 并传入了 Result（即 Promise<UserX>）作为泛型参数。
由于 Result 是一个 Promise 类型，所以 PromiseRes<Result> 
的类型会被推断为 UserX。因此，r 的类型就是 UserX */
interface UserXx {
  name: string
  age: number
}

type Result1 = Promise<Promise<Promise<UserXx>>>

type PromiseRes1<T> = T extends Promise<infer R> ? PromiseRes1<R> : T
/* T extends Promise<infer R> 是一个条件类型检查。
这里，我们检查 T 是否是一个 Promise 类型，如果是，
则尝试推断出 Promise 解析后的类型 R。 
2 ? PromiseRes<R> : T 是条件类型的结果部分。
如果 T 是一个 Promise 类型，则 PromiseRes1<T> 的类型是 PromiseRes1<R>，
其中 R 是 Promise 解析后的类型。
如果 T 不是一个 Promise 类型，则 PromiseRes1<T> 的类型就是 T 本身。
 */
type r1 = PromiseRes1<Result1>

// 对象属性 的类型并且返回 元组类型
let objax = {
  name: '小满',
  age: 123,
}
type protyKey<T> = T extends { name: infer U; age: infer U } ? U : T
// 如果同一个对象使用一个变量就会产生协变，返回值就是联合类型
type res = protyKey<typeof objax>

type FnType<T> = T extends {
  a: (args: infer U) => void
  b: (args: infer U) => void
}
  ? U
  : never
// 函数会产生逆变，此时返回的值是一个交叉类型 string & number 怎么可能一个类型同时是string又是number不可能所以是never
type T = FnType<{ a: (args: number) => void; b: (args: string) => void }>

// ps3
type Arr12 = [4, 3, 2, 1]
// type Arr123 = [1, 2, 3, 4]

type ReveArr<T extends any[]> = T extends [infer First, ...infer rest] ? [...ReveArr<rest>, First] : T

type Res = ReveArr<Arr12>
// let a223:Res = [1,2,3,4]
